package cn.com.zero.front.auth.controller;

import cn.com.zero.api.message.dubbo.IMessageService;
import cn.com.zero.base.constant.ZeroRegexPatternConstants;
import cn.com.zero.base.exception.ErrorCodeException;
import cn.com.zero.base.vo.ResponseVO;
import cn.com.zero.common.auth.security.po.AuthUserPO;
import cn.com.zero.common.auth.security.vo.LoginUserInfoVO;
import cn.com.zero.front.auth.constant.FrontAuthConstants;
import cn.com.zero.front.auth.constant.ValidationRule;
import cn.com.zero.front.auth.po.UserInfoPO;
import cn.com.zero.front.auth.service.IRegisterService;
import cn.com.zero.front.auth.service.IUserService;
import cn.com.zero.web.controller.BaseController;
import cn.com.zero.web.util.HttpRequestUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.Pattern;

/**
 * @author liuxh
 * @version 1.0.0
 * @Description 注册Controller
 * @createTime 2023/3/29 16:49
 */
@Validated
@RestController
@Api(tags = "注册接口")
@RequestMapping("/front/auth/register")
public class RegisterController extends BaseController {

    private IRegisterService registerService;
    private IMessageService messageService;
    private IUserService userService;


    @ApiOperation("手机号注册时发送验证码")
    @ApiImplicitParam(paramType = "query", name = "mobilePhone", required = true, value = "手机号")
    @PostMapping("/sendVerifyCode")
    public void sendVerifyCodeM(@Pattern(regexp = ZeroRegexPatternConstants.MOBILE_EX) @RequestParam("mobilePhone") String mobilePhone) {
        try {
            String requestIp = HttpRequestUtil.getRequestIp();
            // 判断手机号是否已经存在
            AuthUserPO userPO = userService.queryUserByMobilePhone(mobilePhone);
            if (userPO != null) {
                logger.debug("用户注册时，手机号已经存在，手机号：" + mobilePhone);
                return;
            }
            // 发注册验证码
            messageService.sendVerificationCode(mobilePhone, FrontAuthConstants.CODE_MESSAGE_TYPE_REGISTER_MOBILE, requestIp);
            logger.debug("手机号注册验证码发送成功，手机号：{}", mobilePhone);
        } catch (Exception e) {
            logger.error("手机号注册发送验证码异常", e);
        }
    }


    @ApiOperation("手机号注册")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "mobilePhone", required = true, value = "手机号,不允许为空"),
            @ApiImplicitParam(paramType = "query", name = "verifyCode", required = true, value = "验证码,不允许为空"),
            @ApiImplicitParam(paramType = "query", name = "is_login", value = "是否登录，true：是 false：否，可为null，默认不需登录")
    })
    @PostMapping("/mobile")
    public ResponseVO registerM(@Pattern(regexp = ZeroRegexPatternConstants.MOBILE_EX) @RequestParam("mobilePhone") String mobilePhone,
                                @RequestParam("verifyCode") String verifyCode,
                                @RequestParam(value = "is_login", required = false, defaultValue = "false") Boolean is_login) {
        UserInfoPO userInfoPO = checkVerifyCodeAndRegister(mobilePhone, verifyCode, null);
        // 用户登录
        if (is_login) {
            // 用户登录
            LoginUserInfoVO loginUserInfoVO = registerService.loginUser(userInfoPO);
            return ResponseVO.success(loginUserInfoVO);
        }
        return ResponseVO.success(null);
    }


    @ApiOperation("用户名密码方式注册")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "userName", required = true, value = "用户名"),
            @ApiImplicitParam(paramType = "query", name = "password", required = true, value = "密码,不允许为空，客户端限制 6~18 位长度，字母+数字，需要在客户端对新密码进行 MD5 加密后传到服务端"),
            @ApiImplicitParam(paramType = "query", name = "avatar", value = "头像图片文件，可为null"),
            @ApiImplicitParam(paramType = "query", name = "is_login", value = "是否登录，true：是 false：否，可为null，默认不需登录")
    })
    @PostMapping("/userName")
    public ResponseVO registerU(@RequestParam("userName") String userName,
                                @Pattern(regexp = ValidationRule.PASSWORD_EX) @RequestParam("password") String password,
                                @RequestParam(value = "avatar", required = false) MultipartFile avatar,
                                @RequestParam(value = "is_login", required = false, defaultValue = "false") Boolean is_login) {
        // 添加用户
        UserInfoPO userInfoPO = registerService.registerByUserName(userName, password, avatar);
        if (is_login) {
            // 用户登录
            LoginUserInfoVO loginUserInfoVO = registerService.loginUser(userInfoPO);
            return ResponseVO.success(loginUserInfoVO);
        }
        return ResponseVO.success(null);
    }

    @ApiOperation("手机号密码注册")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "query", name = "mobilePhone", required = true, value = "手机号,不允许为空"),
            @ApiImplicitParam(paramType = "query", name = "password", required = true, value = "密码,不允许为空，客户端限制 6~18 位长度，字母+数字，需要在客户端对新密码进行 MD5 加密后传到服务端"),
            @ApiImplicitParam(paramType = "query", name = "verifyCode", required = true, value = "验证码,不允许为空"),
            @ApiImplicitParam(paramType = "query", name = "is_login", value = "是否登录，true：是 false：否，可为null，默认不需登录")
    })
    @PostMapping("/mobilePwd")
    public ResponseVO registerMP(@Pattern(regexp = ZeroRegexPatternConstants.MOBILE_EX) @RequestParam("mobilePhone") String mobilePhone,
                                 @Pattern(regexp = ValidationRule.PASSWORD_EX) @RequestParam("password") String password,
                                 @RequestParam("verifyCode") String verifyCode,
                                 @RequestParam(value = "is_login", required = false, defaultValue = "false") Boolean is_login) {

        UserInfoPO userInfoPO = checkVerifyCodeAndRegister(mobilePhone, verifyCode, password);
        if (is_login) {
            // 用户登录
            LoginUserInfoVO loginUserInfoVO = registerService.loginUser(userInfoPO);
            return ResponseVO.success(loginUserInfoVO);
        }
        return ResponseVO.success(null);
    }


    /**
     * 手机号校验验证码 并 注册
     *
     * @param mobilePhone 手机号
     * @param verifyCode  验证码
     * @param password    密码
     */
    private UserInfoPO checkVerifyCodeAndRegister(String mobilePhone, String verifyCode, String password) {
        Long res = messageService.checkVerificationCode(mobilePhone, FrontAuthConstants.CODE_MESSAGE_TYPE_REGISTER_MOBILE, verifyCode);
        if (res == null || res < 0) {
            throw new ErrorCodeException(-20001L);
        }
        // 添加用户
        return registerService.registerByMobile(mobilePhone, password);
    }


    @Autowired
    public void setRegisterService(IRegisterService registerService) {
        this.registerService = registerService;
    }

    @DubboReference
    public void setMessageService(IMessageService messageService) {
        this.messageService = messageService;
    }

    @Autowired
    public void setUserService(IUserService userService) {
        this.userService = userService;
    }
}
